<template>
    <rx-dialog @handOk="okFun" @cancel="cancel" :showcancel="false" :showok="showOkBtn">
        <rx-layout>
            <div slot="center">
                <a-spin :tip="i18n('appImport.processing','正在处理...')" :spinning="isSpinning">
                    <div style="padding: 0 20px;overflow: hidden;">
                        <a-form :form="form">
                            <div class="title-div" v-show="step==1 || step==2">
                                {{i18n('appImport.step1','第一步')}}
                            </div>
                            <div v-show="step==1  || step==2">
                                    <a-upload
                                        accept=".zip"
                                        :multiple="false"
                                        :file-list="fileList"
                                        :before-upload="beforeFileUpload"
                                        :remove="removeFile"
                                    >
                                        <a-button>
                                            <a-icon type="folder-open"/>
                                            {{i18n('appImport.select','选择...')}}
                                        </a-button>
                                    </a-upload>

                            </div>
                            <div class="title-div" v-if="step==2" style="margin-top: 20px;">
                                {{i18n('appImport.step2','第二步')}}
                            </div>
                            <div v-if="step==2">
                                    <a-button type="primary" @click="handleUpload()">
                                        <a-icon type="upload"/>
                                        {{$ti18('rxList.upload','上传')}}
                                    </a-button>
                            </div>
                            <div  v-if="step==1  || step==2" style="color: darkred;margin-top: 20px;">
                                    {{i18n('appImport.reminder','温馨提醒：如果您是升级应用，建议先备份一下该应用相关的数据库！')}}
                            </div>
                            <div class="title-div" v-if="step==3">
                                {{i18n('appImport.step3','第三步')}}{{ checkMsg }}
                            </div>
                            <template v-if="step==3">
                                <a-tabs default-active-key="1" >
                                    <a-tab-pane key="1" :tab="i18n('appImport.importInformation','导入信息')">
                                        <a-row v-if="checkValid">
                                            <div v-if="showDsMsg" style="color: red;margin-bottom: 5px;">
                                                {{i18n('appImport.specialStart','特别提醒：应用中使用了自定义数据源，')}}{{dsMessageData}}。
                                                <br/>{{i18n('appImport.specialEnd','您可以先手工建立一个数据库(要有undo_log表)...')}}
                                            </div>
                                        </a-row>
                                        <a-row v-if="checkValid">
                                            <a-table v-if="refreshTable" :columns="columns" :data-source="checkData" :pagination="false" id="chkTable"
                                                     :scroll="{y:320}"  ref="checkTable" :rowSelection="rowSelection" rowKey="tableName" >
                                                <template slot="operation" slot-scope="text, record, index">
                                                    <a v-if="record.repeatQty > 0" @click="selectData(record, index)">{{i18n('appImport.selectData','选择数据')}}</a>
                                                </template>
                                            </a-table>
                                        </a-row>
                                        <a-row v-if="checkValid" style="margin-top: 20px; padding-left: 30px;">
                                            <a-col span="10">
                                                <a-checkbox @click="selectAll($event)" :defaultChecked="true" >
                                                    <span :title="i18n('appImport.ifSelected','选中则意味着将覆盖ID相同的记录')">{{i18n('appImport.selectAll','全选/全不选')}}</span></a-checkbox>
                                            </a-col>

                                            <a-col span="14" style="text-align: right;">
                                                <span style="margin-right: 20px;">
                                                    <a-checkbox :checked="backupImport" @change="backupImport=$event.target.checked"  style="margin-right: 6px"/>{{i18n('appImport.backup','是否备份')}}
                                                    <a-tooltip>
                                                      <template slot="title">
                                                        {{(treeId ? i18n('appImport.app','应用') : i18n('appImport.data','数据')) + i18n('appImport.importConfirmTip','导入将会覆盖原数据，有数据丢失的风险，请问你是否需要备份数据表？')}}
                                                      </template>
                                                      <a-icon type="question-circle" />
                                                    </a-tooltip>
                                                </span>
                                                <span style="margin-right: 20px;">
                                                    <a-checkbox :checked="asyncImport" @change="asyncImport=$event.target.checked"  style="margin-right: 6px"/>{{i18n('appImport.async','异步')}}
                                                </span>

                                                <a-button type="primary" @click="handleImport()" style="margin-top: -5px;" v-show="btnCanImport">
                                                    <a-icon type="import"/>
                                                    {{i18n('appImport.confirmImport','确认导入')}}
                                                </a-button>
                                            </a-col>
                                        </a-row>
                                    </a-tab-pane>

                                    <a-tab-pane key="3" :tab="i18n('appImport.changeSQL','变更SQL')" v-if="alertSql" >
                                        <a-textarea v-model="alertSql" style="height: 400px;"></a-textarea>
                                    </a-tab-pane>
                                    <a-tab-pane key="2" :tab="i18n('appImport.errorMsg','错误信息')"  v-if="checkInfo.errMsg" >
                                        <a-textarea v-model="errMsg" style="height: 400px;"></a-textarea>
                                    </a-tab-pane>
                                </a-tabs>

                            </template>

                            <!-- 保留第四步 -->
                            <div class="title-div" v-if="step==4">
                                {{i18n('appImport.step4','第四步')}}
                            </div>
                            <a-row v-if="step==4">
                                <a-col :span="24">
                                    <div style="height: 500px;box-sizing: border-box;width: 100%;padding-right: 1px">
                                        <rx-monaco-editor
                                            ref="monacoes"
                                            :language="monacoeLanguage"
                                            v-model="alterSqls"
                                        >
                                        </rx-monaco-editor>
                                    </div>
                                </a-col>
                            </a-row>
                        </a-form>
                    </div>
                </a-spin>
            </div>
        </rx-layout>
    </rx-dialog>
</template>
<script>
import {BaseForm, RxDialog,  Util, RxMonacoEditor,RxSelect} from "@lowcode/jpaas-common-lib";
import SysAppApi from "@/api/system/core/sysApp";
import AppImportCoverData from '@/views/modules/system/core/AppImportCoverData.vue';
import AppImportBackupTable from '@/views/modules/system/core/AppImportBackupTable.vue';
export default {
    name: 'app-import',
    mixins: [BaseForm],
    components: {
        RxDialog,RxSelect,
        RxMonacoEditor,
        AppImportCoverData,
        AppImportBackupTable
    },
    props: {
        layerid: String,
        lydata: Object,
        destroy: Function,
        treeId: {
            type: String
        },
        callback: {
            type: Function
        }
    },
    data() {
        return {
            isSpinning: false,
            tip: '正在处理...',
            step: 1,
            fileList: [],
            file: {},
            showOkBtn: false,
            checkValid: false,
            checkData: [],
            //检查返回信息
            checkInfo:{},
            checkMsg: "",
            showDsMsg:false,
            dsMessageData:"",
            selectedKeys:[],
            selectedRows:[],

            btnCanImport:true,
            columns: [{
                title: this.$ti18('rxList.index','序号'),
                dataIndex: 'index',
                key: 'index',
                align: 'center',
                width: 50,
                customRender: (text, record, index) => `${index + 1}`,
            }, {
                title: this.i18n('appImport.table','表名'),
                dataIndex: 'tableDesc',
                key: 'tableDesc',
                width: 120,
            }, {
                title: this.i18n('appImport.tableName','物理表名'),
                dataIndex: 'tableName',
                key: 'tableName',
                width: 165,
                sorter: (a, b) => a.tableName.localeCompare(b.tableName),
            },
                {
                    title: this.i18n('appImport.totalQty','总记录数'),
                    dataIndex: 'totalQty',
                    key: 'totalQty',
                    width: 100,
                    align: 'right',
                    sorter: (a, b) => a.totalQty - b.totalQty,
                },
                {
                    title: this.i18n('appImport.repeatQty','重复记录数'),
                    dataIndex: 'repeatQty',
                    key: 'repeatQty',
                    width: 110,
                    align: 'right',
                    sorter: (a, b) => a.repeatQty - b.repeatQty,
                }, {
                    title: this.i18n('appImport.message','用户实体校验'),
                    dataIndex: 'message',
                    key: 'message',
                    align: 'center',
                    width: 120,
                },
                {
                    title: this.i18n('appImport.selectOrTotalData','已选数据/总数据'),
                    dataIndex: 'cover',
                    key: 'cover',
                    align: 'center'
                },
                {
                    title: this.$ti18('rxList.action','操作'),
                    dataIndex: 'operation',
                    key: 'operation',
                    align: 'center',
                    width: 100,
                    scopedSlots: {customRender: 'operation'}
                }
            ],
            fileZipTypes: ["application/x-zip-compressed", "application/zip"],
            monacoeLanguage: "sql",
            alterSqls: "",
            refreshTable: true,
            overrides: [],
            checkResourceData: [],
            backTableData: [],
            //支持异步导入
            asyncImport:true,
            //是否覆盖数据
            backupImport:true
        }
    },
    created() {
        this.backTableData = []
    },
    computed: {
        rowSelection() {
            return {
                //columnTitle:"ID相同的记录则覆盖",
                columnTitle:{
                    tag:'span',
                    text:this.i18n('appImport.overwrite','是否覆盖'),
                    data:{style:'color:blue',attrs:{title:this.i18n('appImport.ifSelected','选中则意味着将覆盖ID相同的记录')}}
                },
                columnWidth:80,
                onChange: (selectedRowKeys, selectedRows) => {
                    this.selectedKeys=selectedRowKeys;
                    this.setSelectAllOrNo(selectedRowKeys, selectedRows);
                },
                selectedRowKeys:this.selectedKeys
            };
        },
        errMsg(){
            return this.getResult("errMsg");
        },
        alertSql(){
            //if(this.checkInfo)
            return this.getResult("alertSql");

        }
    },
    methods: {
        // 是否全覆盖选择或者取消
        setSelectAllOrNo(selectedRowKeys, selectedRows) {
            // 差集
            let arr = this.checkData.filter(v => {
                return selectedRows.every(n => JSON.stringify(n) !== JSON.stringify(v))
            })
            if (arr.length == 0) {
                this.overrides.forEach(data => {
                    data.type = 'all'
                })
                this.checkData.forEach(data => {
                    data.cover = data.repeatQty + "/" + data.totalQty;
                })
            } else {
                let overridesLength = this.overrides.length;
                let arrLength = arr.length;
                for (let  i = 0; i < arrLength; i++) {
                   for (let j = 0; j < overridesLength; j++) {
                       if (arr[i].tableName === this.overrides[j].tableName) {
                           this.overrides[j].type = 'part';
                           this.overrides[j].ids = [];
                           this.overrides[j].tableDesc = this.checkData[j].tableDesc;
                           this.checkData[j].cover = "0/" + this.checkData[j].totalQty;
                           break;
                       }
                   }
                }
            }
            console.log(this.overrides)
        },
        // 重复数据选择
        selectData(record, index) {
            let self_ = this;
            Util.open(
                {
                    component: AppImportCoverData,
                    curVm: this,
                    widthHeight: ['1100px', '620px'],
                    title: self_.i18n('appImport.selectOverrideData','选择覆盖数据'),
                    data: {
                        repeatData: record.repeatDataList,
                        columnData: record.columnList,
                        tableName: record.tableName,
                        tableIndex: index,
                        type: this.overrides[index].type,
                        ids: this.overrides[index].ids
                    }
                },function (action,data) {
                    if (data != null) {
                        let index = data.tableIndex;
                        let obj = self_.checkData[index];
                        self_.checkData[index].cover = data.overridesTotal + obj.cover.substring(obj.cover.indexOf("/"), obj.cover.length)
                        self_.overrides[index].type = data.overridesType;
                        self_.overrides[index].ids = data.overrides;
                        self_.overrides[index].tableDesc = obj.tableDesc;
                        if (data.overridesType == 'part') {
                            self_.selectedKeys = self_.selectedKeys.filter(item => item != data.tableName);
                        } else {
                            if (!self_.selectedKeys.includes(data.tableName)) {
                                self_.selectedKeys.push(data.tableName)
                            }
                        }
                        self_.refreshTable = false;
                        self_.$nextTick(function () {
                            self_.refreshTable = true;
                        })
                    }
                });
        },
        i18n(name,text,key){
            return this.$ti18(name,text,"SysApp",key);
        },
        getResult(attr){
            let ary=[];

            for(let i=0;i<this.checkInfo.length;i++){
                let row=this.checkInfo[i];
                let msg=row[attr];
                if(msg){
                    ary.push(msg);
                }
            }
            if(ary.length>0){
                return ary.join("\r\n");
            }
            return "";
        },
        selectAll(event){
            let chk=true;
            if(event){
                chk=event.target.checked;
            }
            let rowKeys=[];
            if (chk){
                let data;
                for(data of this.checkData) {
                    rowKeys.push(data.tableName);
                    this.overrides.push({
                        tableName: data.tableName,
                        tableDesc: data.tableDesc,
                        type: 'all',
                        ids: []
                    })
                }
            }
            this.selectedKeys=rowKeys;
        },
        removeFile(info) {
            this.fileList.splice(0, 1);
            this.file = {};
        },
        beforeFileUpload(file) {
            this.backTableData = [];
            if (!file || !file.type || this.fileZipTypes.indexOf(file.type) == -1) {
                this.$confirm({
                    title: this.$ti18('rxMsa.masWarn.delInfo','警告'),
                    zIndex: 20000,
                    content: this.i18n('msa.uploadTips','请选择正确的压缩文件（zip格式）！'),
                    okText: this.$ti18('rxForm.ackBtn','确认'),
                    cancelText: this.$ti18('rxForm.cancelBtn','取消'),
                });
                return;
            }
            this.step = 2;
            this.file = file;
            this.fileList.push({
                uid: file.uid,
                name: file.name,
                status: 'done',
                url: null
            });
            //限制只能上传一个文件
            this.fileList = this.fileList.slice(-1);
            return false;
        },
        checkDatasource(){
            this.showDsMsg=false;
            for(let data of this.checkData) {
                if(data.tableName=='form_datasource_def'  && data.code==1){
                    this.showDsMsg=true;
                    this.dsMessageData=data.message;
                    this.btnCanImport=false;
                    return ;
                }
            }
        },
        uploadFile(formData) {
            let self = this;
            this.isSpinning = true;
            SysAppApi.importCheck(formData).then(res => {
                self.step = 3;
                self.isSpinning = false;
                self.checkMsg = res.message;
                if (!res.success) {
                    //导入失败
                    return;
                }

                self.checkInfo=res.data;
                self.checkResourceData = res.data;
                self.checkValid = true;
                for(let i=0;i<res.data.length;i++){
                    let row=res.data[i];
                    if(row.errMsg){
                        self.checkMsg =row.errMsg;
                        self.checkValid = false;
                        return;
                    }
                    row.checkInfoList.forEach(data => {
                        data.cover = data.repeatQty + "/" + data.totalQty;
                    })
                    let list=row.checkInfoList;
                    self.checkData.push(...list);
                }

                self.checkDatasource();
                self.selectAll(null);
            });
        },
        confirmTable() {
            let self_ = this;
            let alterSql = this.getResult("alertSql")
            let content = (self_.treeId ? self_.i18n('appImport.app','应用') : self_.i18n('appImport.data','数据')) + self_.i18n('appImport.sqlChangeTip','导入存在SQL变更，请复制变更SQL到数据库手动执行成功后，再继续下一步！');
            if (alterSql && alterSql.length > 0) {
                this.$confirm({
                    title: self_.i18n('appImport.sqlConfirm','变更SQL执行提醒？'),
                    content: content,
                    zIndex: 10000,
                    okText: self_.i18n('form.yes','是'),
                    okType: 'danger',
                    cancelText: self_.i18n('form.no','否'),
                    onOk() {
                        self_.doImport();
                    },
                    onCancel() {
                    }
                })
            } else {
                self_.doImport();
            }
        },
        handleImport() {
            let self_ = this;
            if (self_.backupImport){
              Util.open(
                  {
                    component: AppImportBackupTable,
                    curVm: self_,
                    widthHeight: ['1100px', '620px'],
                    title: self_.i18n('appImport.waitTable','待备份数据表'),
                    data: {
                      override: self_.overrides,
                      checkData: self_.checkData,
                      checkResourceData: self_.checkResourceData,
                      callback: function (message) {

                      }
                    }
                  },function (action,data) {
                    if (data && data.length > 0) {
                      self_.doTableBackup(data)
                    } else {
                      self_.confirmTable()
                    }
                  });
            } else {
              self_.confirmTable()
            }
        },
        doTableBackup(backup) {
            let self_ = this;
            this.isSpinning = true;
            this.tip = this.i18n('appImport.tableBackupTip','数据备份中...');
            SysAppApi.backupTable(backup).then(res => {
                self_.isSpinning = false;
                if (res.success) {
                    self_.backTableData = backup;
                    self_.confirmTable();
                    self_.$message.success(self_.i18n('appImport.backupSuccess','数据表备份成功!'))
                } else {
                    self_.backTableData = [];
                    self_.$message.error(self_.i18n('appImport.backupFail','数据表备份失败:') + res.message)
                }
            }).catch(res => {
                self_.isSpinning = false;
                self_.backTableData = [];
                //self_.$message.error("服务器错误，数据表备份失败!")
            });
        },
        // 导入
        doImport() {
            this.tip = this.i18n('appImport.importTip','正在导入中...');
            let self_ = this;
            this.isSpinning = true;
            let formData = new FormData();
            formData.append('zipFile', this.file);
            formData.append('fileName', Util.encryptWord(this.file.name,true));
            formData.append('overrides', Util.encryptWord(JSON.stringify(this.overrides),true));
            formData.append('treeId', Util.encryptWord(this.treeId,true));
            formData.append("alertSql", this.getResult("alertSql"));
            formData.append("async", this.asyncImport)

            //调用导入接口
            SysAppApi.doImport(formData).then(res => {
                self_.isSpinning = false;
                let message = res.message;
                if (!res.success) {
                    message = this.i18n('appImport.importFailed','导入失败：') + res.message;
                    //self_.rollBackTable();
                    self_.callback(false, message);
                } else {
                    self_.callback(true, message);
                    let data = res.data;
                    //有延迟的SQL语句
                    if(data != null && data.length > 0){
                        self_.showAlterSqls(data);
                        return ;
                    }
                }
                //关闭弹窗
                self_.okFun();
            }).catch(res => {
                self_.isSpinning = false;
                console.log("导入出错："+res);
            });
        },
        // 回顾备份表
        rollBackTable() {
            if (this.backTableData.length > 0) {
                SysAppApi.rollBackTable(this.backTableData).then(res => {
                    console.log("表格回滚成功！");
                    console.log(res);
                })
            }
        },
        showAlterSqls(data) {
            //第四步,显示 需要手动执行的SQL
            var sqls = [];
            for (var i = 0; data && i < data.length; i++) {
                var sqlObj = data[i];
                sqls.push(sqlObj.sql);
            }
            if (sqls.length > 0) {
                this.alterSqls = sqls.join("\n");
            }
            this.step=4;
            this.showOkBtn=true;
        },
        handleUpload() {
            if (this.fileList.length === 0) {
                this.$confirm({
                    title: this.$ti18('rxMsa.masWarn.delInfo','警告'),
                    zIndex: 20000,
                    content: this.i18n('msa.importFormat','请选择需要导入的压缩文件（zip格式）！'),
                    okText: this.$ti18('rxForm.ackBtn','确认'),
                    cancelText: this.$ti18('rxForm.cancelBtn','取消'),
                });
                return;
            }
            const {
                fileList
            } = this;
            const formData = new FormData();
            let timestamp = new Date().getTime();
            formData.append("time", Util.encryptWord(timestamp,true));
            formData.append('zipFile', this.file);
            formData.append('treeId', Util.encryptWord(this.treeId,true));
            this.uploadFile(formData);
        },
        okFun() {
            Util.closeWindow(this, "ok");
        },
        cancel() {
            Util.closeWindow(this, "cancel");
        }
    }
}
</script>
<style scoped>
.title-div {
    padding: 10px 0;
    font-weight: bold;
    color: navy;
}

* >>> .ant-table-thead > tr > th {
    text-align: center;
}

* >>> .ql-snow .ql-picker-label::before {
    vertical-align: top;
}

* >>> .ql-snow .ql-color-picker .ql-picker-label svg,
* >>> .ql-snow .ql-icon-picker .ql-picker-label svg {
    vertical-align: top;
}

.avatar-uploader > .ant-upload {
    width: 128px;
    height: 128px;
}

.ant-upload-select-picture-card i {
    font-size: 32px;
    color: #999;
}
.ant-upload-select-picture-card .ant-upload-text {
    margin-top: 8px;
    color: #666;
}
</style>